package com.dj.mingkong.admin.biz.scheduler;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dj.mingkong.admin.biz.core.config.GenHtmlConfig;
import com.dj.mingkong.admin.biz.enums.NavMenuEnum;
import com.dj.mingkong.admin.biz.repository.database.music.AlbumRepository;
import com.dj.mingkong.admin.biz.repository.database.music.BoxRepository;
import com.dj.mingkong.admin.biz.repository.database.music.MusicRepository;
import com.dj.mingkong.admin.biz.repository.database.music.MusicianRepository;
import com.dj.mingkong.admin.biz.repository.database.system.DictionaryRepository;
import com.dj.mingkong.admin.biz.scheduler.vo.gen.*;
import com.dj.mingkong.common.constant.CommonConstants;
import com.dj.mingkong.common.enums.MusicStatusEnum;
import com.dj.mingkong.common.enums.MusicianStatusEnum;
import com.dj.mingkong.common.enums.StatusEnum;
import com.dj.mingkong.common.infrastructure.eo.database.music.AlbumEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.MusicEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.MusicianEo;
import com.dj.mingkong.common.infrastructure.eo.database.system.DictionaryEo;
import com.dj.mingkong.common.util.LocalDateTimeUtils;
import com.dj.mingkong.common.util.SmartBeanCopy;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import freemarker.template.Configuration;
import freemarker.template.Template;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfig;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.*;

import static com.dj.mingkong.admin.biz.constant.GenHtmlConstants.*;


/**
 * @author zenglonghui
 * @date: 2022/10/11 10:46
 */
@Slf4j
@Component
public class GenHtmlJob {
    @Resource
    private GenHtmlConfig genHtmlConfig;
    @Resource
    private FreeMarkerConfig freeMarkerConfig;
    @Resource
    private DictionaryRepository dictionaryRepository;
    @Resource
    private MusicRepository musicRepository;
    @Resource
    private AlbumRepository albumRepository;
    @Resource
    private MusicianRepository musicianRepository;
    @Resource
    private BoxRepository boxRepository;

    @XxlJob("genIndexHtml")
    public void genIndexHtml() {
        try {
            XxlJobHelper.log("genIndexHtml start......");
            log.info("genIndexHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getIndexFtlName());

            //3.创建模板使用的数据集 可以是pojo 也可以是map 一般使用map
            Map<String, Object> indexMap = new HashMap<>(11);

            //组装导航栏数据
            indexMap.put("navMenuList", getNavMenuList());

            //组装首页音乐分类数据
            indexMap.put("classifyList", getClassifyList());

            //组装推荐音乐数据
            indexMap.put("recommendMusicMap", getMusicMap(MUSIC_RECOMMEND));
            //组装最新音乐数据
            indexMap.put("newestMusicMap", getMusicMap(MUSIC_NEW));
            //组装热播音乐数据
            indexMap.put("hotMusicMap", getMusicMap(MUSIC_HOT));
            //组装精品音乐数据
            indexMap.put("boutiqueMusicMap", getMusicMap(MUSIC_BOUTIQUE));
            //组装车载音乐数据
            indexMap.put("vehicleMusicMap", getMusicMap(MUSIC_VEHICLE));

            //组装排行榜串烧音乐数据
            indexMap.put("rankingOwnerMusicMap", getRankingMusicMap(ALL_OWNER));
            //组装排行榜单曲音乐数据
            indexMap.put("rankingSingleMusicMap", getRankingMusicMap(ALL_SINGLE));

            //组装音乐专辑数据
            indexMap.put("albumNewList", getAlbumList(TYPE_NEW));
            indexMap.put("albumHotList", getAlbumList(TYPE_HOT));

            //组装音乐制作人数据
            indexMap.put("musicianNewList", getMusicianList(TYPE_NEW));
            indexMap.put("musicianHotList", getMusicianList(TYPE_HOT));

            //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
            Writer out = new FileWriter(genHtmlConfig.getIndexFilePath() + "index.html");
            //5.调用模板对象的process方法 输出文件
            template.process(indexMap, out);
            //关闭流
            out.close();
            XxlJobHelper.log("genIndexHtml end........");
            log.info("genIndexHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genIndexHtml error", e);
            log.error("genIndexHtml error", e);
        }
    }

    @XxlJob("genPlayHtml")
    public void genPlayHtml() {
        try {
            XxlJobHelper.log("genPlayHtml start......");
            log.info("genPlayHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getPlayFtlName());

            //3.创建模板使用的数据集 可以是pojo 也可以是map 一般使用map
            Map<String, Object> playMap = new HashMap<>(8);

            //组装导航栏数据
            List<NavMenuVo> navMenuList = getNavMenuList();
            playMap.put("navMenuList", navMenuList);

            //获取所有审核通过的音乐数据
            List<PlayMusicVo> playMusicVoList = musicRepository.getMapper().selectPlayMusicList();
            if (CollectionUtils.isEmpty(playMusicVoList)) {
                return;
            }
            int i = 1;
            for (PlayMusicVo music : playMusicVoList) {
                XxlJobHelper.log("音乐总数量:{}, 当前数量:{}, ID:{}", playMusicVoList.size(), i, music.getId());
                log.info("音乐总数量:{}, 当前数量:{}, ID:{}", playMusicVoList.size(), i, music.getId());
                //组装所属导航
                playMap.put("navMenu", navMenuList.stream().filter(nav -> Objects.equals(nav.getFullKey(), music.getNavMenuKey()))
                        .findFirst().orElse(NavMenuVo.builder().build()));

                //组装上周排行榜音乐数据
                playMap.put("weekMusicList", getWeekMusicListByNavMenuKey(music.getNavMenuKey()));

                playMap.put("music", music);

                //组装音乐人数据
                MusicianEo musicianEo = musicianRepository.getById(music.getMusicianId());
                playMap.put("musician", SmartBeanCopy.copy(musicianEo, PlayMusicianVo.class));

                //组装相似音乐数据
                playMap.put("likeMusicList", getLikeMusicList(music));

                //组装音乐人热歌榜数据
                playMap.put("musicianHotMusicList", getMusicianHotMusicList(music.getMusicianId()));

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getPlayFilePath() + music.getId() + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(playMap, out);
                //关闭流
                out.close();
                i++;
            }
            XxlJobHelper.log("genPlayHtml end........");
            log.info("genPlayHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genPlayHtml error", e);
            log.error("genPlayHtml error", e);
        }
    }

    @XxlJob("genOwnerListHtml")
    public void genOwnerListHtml() {
        try {
            XxlJobHelper.log("genOwnerListHtml start........");
            log.info("genOwnerListHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getOwnerListFtlName());

            Map<String, Object> ownerListMap = getGenHtmlResultMap(NavMenuEnum.OWNER.getDictKey());
            ownerListMap.put("jumpType", 1);

            //获取串烧舞曲音乐列表数据
            Page<ListMusicVo> musicVoPage = getGenListMusicPage(1, NavMenuEnum.OWNER.getDictKey());
            for (int pageNum = 1; pageNum <= musicVoPage.getPages(); pageNum++) {
                XxlJobHelper.log("串烧舞曲总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);
                log.info("串烧舞曲总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);

                //组装音乐列表数据
                ownerListMap.put("musicPage", getGenListMusicPage(pageNum, NavMenuEnum.OWNER.getDictKey()));

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getOwnerListFilePath() + pageNum + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(ownerListMap, out);
                //关闭流
                out.close();
            }
            XxlJobHelper.log("genOwnerListHtml end........");
            log.info("genOwnerListHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genOwnerListHtml error", e);
            log.error("genOwnerListHtml error", e);
        }
    }

    @XxlJob("genSongOwnerListHtml")
    public void genSongOwnerListHtml() {
        try {
            XxlJobHelper.log("genSongOwnerListHtml start........");
            log.info("genSongOwnerListHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getSongOwnerListFtlName());

            Map<String, Object> songOwnerListMap = getGenHtmlResultMap(NavMenuEnum.SONG_OWNER.getDictKey());
            songOwnerListMap.put("jumpType", 2);
            //获取音乐连版页音乐列表数据
            Page<ListMusicVo> musicVoPage = getGenListMusicPage(1, NavMenuEnum.SONG_OWNER.getDictKey());
            for (int pageNum = 1; pageNum <= musicVoPage.getPages(); pageNum++) {
                XxlJobHelper.log("音乐连版总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);
                log.info("音乐连版总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);

                //组装音乐列表数据
                final Page<ListMusicVo> musicPage = getGenListMusicPage(pageNum, NavMenuEnum.SONG_OWNER.getDictKey());
                songOwnerListMap.put("musicPage", musicPage);

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getSongOwnerListFilePath() + pageNum + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(songOwnerListMap, out);
                //关闭流
                out.close();
            }
            XxlJobHelper.log("genSongOwnerListHtml end........");
            log.info("genSongOwnerListHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genSongOwnerListHtml error", e);
            log.error("genSongOwnerListHtml error", e);
        }
    }

    @XxlJob("genCnSingleListHtml")
    public void genCnSingleListHtml() {
        try {
            XxlJobHelper.log("genCnSingleListHtml start........");
            log.info("genCnSingleListHtml start........");

            //获取模板
            Template template = getTemplate(genHtmlConfig.getCnSingleListFtlName());

            Map<String, Object> cnSingleListMap = getGenHtmlResultMap(NavMenuEnum.CN_SINGLE.getDictKey());
            cnSingleListMap.put("jumpType", 3);

            //获取音乐连版页音乐列表数据
            Page<ListMusicVo> musicVoPage = getGenListMusicPage(1, NavMenuEnum.CN_SINGLE.getDictKey());
            for (int pageNum = 1; pageNum <= musicVoPage.getPages(); pageNum++) {
                XxlJobHelper.log("中文单曲总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);
                log.info("中文单曲总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);

                //组装音乐列表数据
                final Page<ListMusicVo> musicPage = getGenListMusicPage(pageNum, NavMenuEnum.CN_SINGLE.getDictKey());
                cnSingleListMap.put("musicPage", musicPage);

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getCnSingleListFilePath() + pageNum + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(cnSingleListMap, out);
                //关闭流
                out.close();
            }
            XxlJobHelper.log("genCnSingleListHtml end........");
            log.info("genCnSingleListHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genCnSingleListHtml error", e);
            log.error("genCnSingleListHtml error", e);
        }
    }

    @XxlJob("genEnSingleListHtml")
    public void genEnSingleListHtml() {
        try {
            XxlJobHelper.log("genEnSingleListHtml start........");
            log.info("genEnSingleListHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getEnSingleListFtlName());

            Map<String, Object> enSingleListMap = getGenHtmlResultMap(NavMenuEnum.EN_SINGLE.getDictKey());
            enSingleListMap.put("jumpType", 4);

            //获取音乐连版页音乐列表数据
            Page<ListMusicVo> musicVoPage = getGenListMusicPage(1, NavMenuEnum.EN_SINGLE.getDictKey());
            for (int pageNum = 1; pageNum <= musicVoPage.getPages(); pageNum++) {
                XxlJobHelper.log("外文单曲总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);
                log.info("外文单曲总页数：{}, 当前页：{}", musicVoPage.getPages(), pageNum);

                //组装音乐列表数据
                final Page<ListMusicVo> musicPage = getGenListMusicPage(pageNum, NavMenuEnum.EN_SINGLE.getDictKey());
                enSingleListMap.put("musicPage", musicPage);

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getEnSingleListFilePath() + pageNum + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(enSingleListMap, out);
                //关闭流
                out.close();
            }
            XxlJobHelper.log("genEnSingleListHtml end........");
            log.info("genEnSingleListHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genEnSingleListHtml error", e);
            log.error("genEnSingleListHtml error", e);
        }
    }

    @XxlJob("genMusicianListHtml")
    public void genMusicianListHtml() {
        try {
            XxlJobHelper.log("genMusicianListHtml start........");
            log.info("genMusicianListHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getMusicianListFtlName());

            Map<String, Object> musicianListMap = getGenHtmlResultMap(NavMenuEnum.MUSICIAN.getDictKey());

            //获取所有音乐人数据
            Page<ListMusicianVo> musicianPage = getMusicianPage(1);
            for (int pageNum = 1; pageNum <= musicianPage.getPages(); pageNum++) {
                XxlJobHelper.log("DJ制作人总页数：{}, 当前页：{}", musicianPage.getPages(), pageNum);
                log.info("DJ制作人总页数：{}, 当前页：{}", musicianPage.getPages(), pageNum);

                //组装音乐人列表数据
                musicianListMap.put("musicianPage", getMusicianPage(pageNum));

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getMusicianListFilePath() + pageNum + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(musicianListMap, out);
                //关闭流
                out.close();
            }
            XxlJobHelper.log("genMusicianListHtml end........");
            log.info("genMusicianListHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genMusicianListHtml error", e);
            log.error("genMusicianListHtml error", e);
        }
    }

    @XxlJob("genAlbumListHtml")
    public void genAlbumListHtml() {
        try {
            XxlJobHelper.log("genAlbumListHtml start........");
            log.info("genAlbumListHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getAlbumListFtlName());

            Map<String, Object> albumListMap = getGenHtmlResultMap(NavMenuEnum.ALBUM.getDictKey());

            //获取所有专辑数据
            Page<ListAlbumVo> albumPage = getAlbumPage(1);
            for (int pageNum = 1; pageNum <= albumPage.getPages(); pageNum++) {
                XxlJobHelper.log("音乐专辑总页数：{}, 当前页：{}", albumPage.getPages(), pageNum);
                log.info("音乐专辑总页数：{}, 当前页：{}", albumPage.getPages(), pageNum);

                //组装专辑列表数据
                albumListMap.put("albumPage", getAlbumPage(pageNum));

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getAlbumListFilePath() + pageNum + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(albumListMap, out);
                //关闭流
                out.close();
            }
            XxlJobHelper.log("genAlbumListHtml end........");
            log.info("genAlbumListHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genAlbumListHtml error", e);
            log.error("genAlbumListHtml error", e);
        }
    }

    @XxlJob("genBoxListHtml")
    public void genBoxListHtml() {
        try {
            XxlJobHelper.log("genBoxListHtml start........");
            log.info("genBoxListHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getBoxListFtlName());

            Map<String, Object> boxListMap = getGenHtmlResultMap(NavMenuEnum.BOX.getDictKey());

            //获取所有歌单数据
            Page<ListBoxVo> boxPage = getBoxPage(1);
            for (int pageNum = 1; pageNum <= boxPage.getPages(); pageNum++) {
                XxlJobHelper.log("音乐歌单总页数：{}, 当前页：{}", boxPage.getPages(), pageNum);
                log.info("音乐歌单总页数：{}, 当前页：{}", boxPage.getPages(), pageNum);

                //组装歌单列表数据
                boxListMap.put("boxPage", getBoxPage(pageNum));

                //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                Writer out = new FileWriter(genHtmlConfig.getBoxListFilePath() + pageNum + ".html");
                //5.调用模板对象的process方法 输出文件
                template.process(boxListMap, out);
                //关闭流
                out.close();
            }
            XxlJobHelper.log("genBoxListHtml end........");
            log.info("genBoxListHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genBoxListHtml error", e);
            log.error("genBoxListHtml error", e);
        }
    }

    @XxlJob("genMusicianHtml")
    public void genMusicianHtml() {
        try {
            XxlJobHelper.log("genMusicianHtml start........");
            log.info("genMusicianHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getMusicianFtlName());

            Map<String, Object> musicianMap = getGenHtmlResultMap(OTHER);

            //获取所有音乐人
            final List<MusicianDetailVo> musicianDetailVos = musicianRepository.getMapper().selectAll();
            if (musicianDetailVos.isEmpty()) {
                return;
            }

            int i = 1;
            for (MusicianDetailVo musician : musicianDetailVos) {
                XxlJobHelper.log("音乐人总数量:{}， 当前数量:{}， ID:{}", musicianDetailVos.size(), i, musician.getId());
                log.info("音乐人总数量:{}， 当前数量:{}， ID:{}", musicianDetailVos.size(), i, musician.getId());

                //组装音乐人数据
                musicianMap.put("musician", musician);

                //获取音乐人的音乐数据
                Page<ListMusicVo> musicVoPage = getMusicPageByMusicianId(1, musician.getId());
                for (int pageNum = 1; pageNum <= musicVoPage.getPages(); pageNum++) {
                    XxlJobHelper.log("音乐人作品总页数:{}， 当前页:{}", musicVoPage.getPages(), pageNum);
                    log.info("音乐人作品总页数:{}， 当前页:{}", musicVoPage.getPages(), pageNum);

                    //组装音乐人的音乐数据
                    musicianMap.put("musicPage", getMusicPageByMusicianId(pageNum, musician.getId()));

                    //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                    Writer out = new FileWriter(genHtmlConfig.getMusicianFilePath() + musician.getId() + "_" + pageNum + ".html");
                    //5.调用模板对象的process方法 输出文件
                    template.process(musicianMap, out);
                    //关闭流
                    out.close();
                }
                i++;
            }
            XxlJobHelper.log("genMusicianHtml end........");
            log.info("genMusicianHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genMusicianHtml error", e);
            log.error("genMusicianHtml error", e);
        }
    }

    @XxlJob("genAlbumHtml")
    public void genAlbumHtml() {
        try {
            XxlJobHelper.log("genAlbumHtml start........");
            log.info("genAlbumHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getAlbumFtlName());

            Map<String, Object> albumMap = getGenHtmlResultMap(OTHER);

            //获取所有专辑
            final List<AlbumDetailVo> albumVos = albumRepository.getMapper().selectAll();
            if (albumVos.isEmpty()) {
                return;
            }

            int i = 1;
            for (AlbumDetailVo albumVo : albumVos) {
                XxlJobHelper.log("音乐专辑总数量:{}， 当前数量:{}， ID:{}", albumVos.size(), i, albumVo.getId());
                log.info("音乐专辑总数量:{}， 当前数量:{}， ID:{}", albumVos.size(), i, albumVo.getId());

                //组装专辑数据
                albumMap.put("album", albumVo);

                //获取专辑的音乐数据
                Page<ListMusicVo> musicVoPage = getMusicPageByAlbumId(1, albumVo.getId());
                for (int pageNum = 1; pageNum <= musicVoPage.getPages(); pageNum++) {
                    XxlJobHelper.log("音乐专辑作品总页数:{}， 当前页:{}", musicVoPage.getPages(), pageNum);
                    log.info("音乐专辑作品总页数:{}， 当前页:{}", musicVoPage.getPages(), pageNum);

                    //组装专辑的音乐数据
                    albumMap.put("musicPage", getMusicPageByAlbumId(pageNum, albumVo.getId()));

                    //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                    Writer out = new FileWriter(genHtmlConfig.getAlbumFilePath() + albumVo.getId() + "_" + pageNum + ".html");
                    //5.调用模板对象的process方法 输出文件
                    template.process(albumMap, out);
                    //关闭流
                    out.close();
                }
                i++;
            }
            XxlJobHelper.log("genAlbumHtml end........");
            log.info("genAlbumHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genAlbumHtml error", e);
            log.error("genAlbumHtml error", e);
        }
    }

    @XxlJob("genBoxHtml")
    public void genBoxHtml() {
        try {
            XxlJobHelper.log("genBoxHtml start........");
            log.info("genBoxHtml start........");
            //获取模板
            Template template = getTemplate(genHtmlConfig.getBoxFtlName());

            Map<String, Object> boxMap = getGenHtmlResultMap(OTHER);

            //获取所有歌单
            final List<BoxDetailVo> boxVos = boxRepository.getMapper().selectAll();
            if (boxVos.isEmpty()) {
                return;
            }

            int i = 1;
            for (BoxDetailVo boxVo : boxVos) {
                XxlJobHelper.log("音乐歌单总数量:{}， 当前数量:{}， ID:{}", boxVos.size(), i, boxVo.getId());
                log.info("音乐歌单总数量:{}， 当前数量:{}， ID:{}", boxVos.size(), i, boxVo.getId());

                //组装歌单数据
                boxMap.put("box", boxVo);

                //获取歌单的音乐数据
                Page<ListMusicVo> musicVoPage = getMusicPageByBoxId(1, boxVo.getId());
                for (int pageNum = 1; pageNum <= musicVoPage.getPages(); pageNum++) {
                    XxlJobHelper.log("音乐歌单作品总页数:{}， 当前页:{}", musicVoPage.getPages(), pageNum);
                    log.info("音乐歌单作品总页数:{}， 当前页:{}", musicVoPage.getPages(), pageNum);

                    //组装歌单的音乐数据
                    boxMap.put("musicPage", getMusicPageByBoxId(pageNum, boxVo.getId()));

                    //4.创建一个writer对象，一般创建FileWriter指定生成的文件名
                    Writer out = new FileWriter(genHtmlConfig.getBoxFilePath() + boxVo.getId() + "_" + pageNum + ".html");
                    //5.调用模板对象的process方法 输出文件
                    template.process(boxMap, out);
                    //关闭流
                    out.close();
                }
                i++;
            }
            XxlJobHelper.log("genBoxHtml end........");
            log.info("genBoxHtml end........");
        } catch (Exception e) {
            XxlJobHelper.log("genBoxHtml error", e);
            log.error("genBoxHtml error", e);
        }
    }

    private Template getTemplate(String ftlName) throws IOException {
        //1.创建一个configuration对象
        Configuration configuration = freeMarkerConfig.getConfiguration();
        //2.加载模板，创建一个模板对象
        return configuration.getTemplate(ftlName);
    }

    private List<NavMenuVo> getNavMenuList() {
        final List<DictionaryEo> dictionaryEos = listByParentKey(NAV_MENU_DICT_KEY);
        return SmartBeanCopy.copy(dictionaryEos, NavMenuVo.class);
    }

    private List<DictionaryEo> listByParentKey(String dictKey) {
        final Optional<DictionaryEo> eoOptional = dictionaryRepository.oneOptByDictKey(dictKey);
        if (eoOptional.isEmpty()) {
            return Collections.emptyList();
        }
        return dictionaryRepository.listByParentId(eoOptional.get().getId());
    }

    private List<IndexClassifyVo> getClassifyList() {
        final List<DictionaryEo> dictionaryEos = listByParentKey(CLASSIFY_DICT_KEY);
        return SmartBeanCopy.copy(dictionaryEos, IndexClassifyVo.class);
    }

    private Map<String, Object> getMusicMap(String classify) {
        final String fullKey = NAV_MENU_DICT_KEY.concat(CommonConstants.FULL_KEY_JOIN);
        Map<String, Object> musicMap = new HashMap<>(5);
        //显示20条数据
        Page<IndexMusicVo> musicPage = new Page<>(1, 20);
        musicMap.put("ownerMusicList",
                musicRepository.getMapper().selectIndexMusicList(musicPage, classify, fullKey.concat(NavMenuEnum.OWNER.getDictKey())));
        musicMap.put("songOwnerMusicList",
                musicRepository.getMapper().selectIndexMusicList(musicPage, classify, fullKey.concat(NavMenuEnum.SONG_OWNER.getDictKey())));
        musicMap.put("cnSingleMusicList",
                musicRepository.getMapper().selectIndexMusicList(musicPage, classify, fullKey.concat(NavMenuEnum.CN_SINGLE.getDictKey())));
        musicMap.put("enSingleMusicList",
                musicRepository.getMapper().selectIndexMusicList(musicPage, classify, fullKey.concat(NavMenuEnum.EN_SINGLE.getDictKey())));
        return musicMap;
    }

    private Map<String, Object> getRankingMusicMap(String type) {
        Map<String, Object> musicMap = new HashMap<>(3);
        //周榜
        musicMap.put("weekMusicList", getRankingMusicList(type, RANKING_WEEK));
        //月榜
        musicMap.put("monthMusicList", getRankingMusicList(type, RANKING_MONTH));
        //季榜
        musicMap.put("quarterMusicList", getRankingMusicList(type, RANKING_QUARTER));
        return musicMap;
    }

    private List<RankingMusicVo> getRankingMusicList(String type, String classify) {
        final String fullKey = NAV_MENU_DICT_KEY.concat(CommonConstants.FULL_KEY_JOIN);
        LambdaQueryWrapper<MusicEo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MusicEo::getStatus, MusicStatusEnum.PASS.getIntVal())
                .orderByDesc(MusicEo::getPopularity);
        if (classify.equals(RANKING_WEEK)) {
            //周榜 发布时间小于本周第一天 大于或等于上周一
            queryWrapper.lt(MusicEo::getReleaseTime, LocalDateTimeUtils.getMondayForThisWeek())
                    .ge(MusicEo::getReleaseTime, LocalDateTimeUtils.getMondayForUpWeek());
        }
        if (classify.equals(RANKING_MONTH)) {
            //月榜 发布时间小于本月第一天 大于或等于上月第一天
            queryWrapper.lt(MusicEo::getReleaseTime, LocalDateTimeUtils.monthStartTime())
                    .ge(MusicEo::getReleaseTime, LocalDateTimeUtils.lastMonthStartTime());
        }
        if (classify.equals(RANKING_QUARTER)) {
            //季度 发布时间小于本季度第一天 大于或等于上季度第一天
            queryWrapper.lt(MusicEo::getReleaseTime, LocalDateTimeUtils.quarterStartTime())
                    .ge(MusicEo::getReleaseTime, LocalDateTimeUtils.lastQuarterStartTime());
        }
        List<String> navMenuKeyList = new ArrayList<>();
        if (type.equals(ALL_OWNER)) {
            //串烧
            navMenuKeyList.add(fullKey.concat(NavMenuEnum.OWNER.getDictKey()));
            navMenuKeyList.add(fullKey.concat(NavMenuEnum.SONG_OWNER.getDictKey()));
        } else {
            //单曲
            navMenuKeyList.add(fullKey.concat(NavMenuEnum.CN_SINGLE.getDictKey()));
            navMenuKeyList.add(fullKey.concat(NavMenuEnum.EN_SINGLE.getDictKey()));
        }
        queryWrapper.in(MusicEo::getNavMenuKey, navMenuKeyList);
        Page<MusicEo> musicEoPage = musicRepository.listPage(queryWrapper, 1, 10);
        return SmartBeanCopy.copy(musicEoPage.getRecords(), RankingMusicVo.class);
    }

    private List<IndexAlbumVo> getAlbumList(String type) {
        LambdaQueryWrapper<AlbumEo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlbumEo::getStatus, StatusEnum.VALID.getIntVal());
        if (TYPE_NEW.equals(type)) {
            queryWrapper.orderByDesc(AlbumEo::getMusicUpdateTime);
        }
        if (TYPE_HOT.equals(type)) {
            queryWrapper.orderByDesc(AlbumEo::getPopularity);
        }
        Page<AlbumEo> albumEoPage = albumRepository.listPage(queryWrapper, 1, 12);
        return SmartBeanCopy.copy(albumEoPage.getRecords(), IndexAlbumVo.class);
    }

    private List<IndexMusicianVo> getMusicianList(String type) {
        LambdaQueryWrapper<MusicianEo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MusicianEo::getStatus, MusicianStatusEnum.PASS.getIntVal());
        if (TYPE_NEW.equals(type)) {
            queryWrapper.orderByDesc(MusicianEo::getMusicUpdateTime);
        }
        if (TYPE_HOT.equals(type)) {
            queryWrapper.orderByDesc(MusicianEo::getPopularity);
        }
        Page<MusicianEo> musicianEoPage = musicianRepository.listPage(queryWrapper, 1, 9);
        return SmartBeanCopy.copy(musicianEoPage.getRecords(), IndexMusicianVo.class);
    }

    private List<RankingMusicVo> getWeekMusicListByNavMenuKey(String navMenuKey) {
        LambdaQueryWrapper<MusicEo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MusicEo::getStatus, MusicStatusEnum.PASS.getIntVal())
                .eq(MusicEo::getNavMenuKey, navMenuKey).orderByDesc(MusicEo::getPopularity);
        List<MusicEo> records = musicRepository.listPage(queryWrapper, 1, 10).getRecords();
        return SmartBeanCopy.copy(records, RankingMusicVo.class);
    }

    private List<RankingMusicVo> getMusicianHotMusicList(Long musicianId) {
        //显示10条数据
        LambdaQueryWrapper<MusicEo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MusicEo::getStatus, MusicStatusEnum.PASS.getIntVal())
                .eq(MusicEo::getMusicianId, musicianId).orderByDesc(MusicEo::getPopularity);
        Page<MusicEo> musicEoPage = musicRepository.listPage(queryWrapper, 1, 10);
        return SmartBeanCopy.copy(musicEoPage.getRecords(), RankingMusicVo.class);
    }

    private List<PlayLikeMusicVo> getLikeMusicList(PlayMusicVo music) {
        PlayLikeMusicQueryVo queryVo = SmartBeanCopy.copy(music, PlayLikeMusicQueryVo.class);
        Page<PlayLikeMusicVo> musicPage = new Page<>(1, 20);
        return musicRepository.getMapper().selectLikeMusicList(musicPage, queryVo).getRecords();
    }

    private Map<String, Object> getGenHtmlResultMap(String navMenuKey) {
        //3.创建模板使用的数据集 可以是pojo 也可以是map 一般使用map
        Map<String, Object> map = new HashMap<>(3);

        //组装导航栏数据
        List<NavMenuVo> navMenuList = getNavMenuList();
        map.put("navMenuList", navMenuList);

        //组装所有音乐下载榜
        map.put("downloadMusicList", getRankingMusicListByType(RANKING_DOWNLOAD));
        //组装所有音乐喜欢榜
        map.put("likeMusicList", getRankingMusicListByType(RANKING_LIKE));

        if (!navMenuKey.equals(OTHER)) {
            //组装所属导航
            map.put("navMenu", navMenuList.stream().filter(nav -> nav.getDictKey().equals(navMenuKey))
                    .findFirst().orElse(NavMenuVo.builder().build()));
        }
        return map;
    }

    private List<RankingMusicVo> getRankingMusicListByType(String type) {
        //显示10条数据
        LambdaQueryWrapper<MusicEo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MusicEo::getStatus, MusicStatusEnum.PASS.getIntVal());
        if (type.equals(RANKING_DOWNLOAD)) {
            //下载榜
            queryWrapper.orderByDesc(MusicEo::getDownloadCount);
        }
        if (type.equals(RANKING_LIKE)) {
            //喜欢榜
            queryWrapper.orderByDesc(MusicEo::getCollectCount);
        }
        Page<MusicEo> musicEoPage = musicRepository.listPage(queryWrapper, 1, 10);
        return SmartBeanCopy.copy(musicEoPage.getRecords(), RankingMusicVo.class);
    }

    private Page<ListMusicVo> getGenListMusicPage(int pageNum, String navMenuKey) {
        final String fullKey = NAV_MENU_DICT_KEY.concat(CommonConstants.FULL_KEY_JOIN);
        Page<ListMusicVo> musicPage = new Page<>(pageNum, genHtmlConfig.getListPageSize());
        return musicRepository.getMapper().selectGenListHtmlMusicPage(musicPage, fullKey.concat(navMenuKey));
    }

    private Page<ListMusicianVo> getMusicianPage(int pageNum) {
        return musicianRepository.getMapper().selectMusicianPage(Page.of(pageNum, genHtmlConfig.getListPageSize()));
    }

    private Page<ListAlbumVo> getAlbumPage(int pageNum) {
        return albumRepository.getMapper().selectAlbumPage(Page.of(pageNum, genHtmlConfig.getListPageSize()));
    }

    private Page<ListBoxVo> getBoxPage(int pageNum) {
        return boxRepository.getMapper().selectBoxPage(Page.of(pageNum, genHtmlConfig.getListPageSize()));
    }

    private Page<ListMusicVo> getMusicPageByMusicianId(int pageNum, Long musicianId) {
        return musicRepository.getMapper().selectMusicianMusicPage(Page.of(pageNum, genHtmlConfig.getListPageSize()), musicianId);
    }

    private Page<ListMusicVo> getMusicPageByAlbumId(int pageNum, Long albumId) {
        return musicRepository.getMapper().selectMusicListByAlbumId(Page.of(pageNum, genHtmlConfig.getListPageSize()), albumId);
    }

    private Page<ListMusicVo> getMusicPageByBoxId(int pageNum, Long boxId) {
        return musicRepository.getMapper().selectMusicListByBoxId(Page.of(pageNum, genHtmlConfig.getListPageSize()), boxId);
    }
}
